package com.ruoyi.common.security.utils;

import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;

public class SM2Utils {

    private static SM2KeyPair sm2KeyPair;

    @Data
    @AllArgsConstructor
    public static class SM2KeyPair {
        // 公钥
        private String publicKey;

        // 前端公钥
        private String publicQKey;

        // 私钥
        private String privateKey;

        public String getPublicKey() {
            return publicKey;
        }

        public void setPublicKey(String publicKey) {
            this.publicKey = publicKey;
        }

        public String getPublicQKey() {
            return publicQKey;
        }

        public void setPublicQKey(String publicQKey) {
            this.publicQKey = publicQKey;
        }

        public String getPrivateKey() {
            return privateKey;
        }

        public void setPrivateKey(String privateKey) {
            this.privateKey = privateKey;
        }
    }

    // 生成密钥对
    public static SM2KeyPair getSm2KeyPair() {
        if (sm2KeyPair == null) {
            SM2 sm2 = SmUtil.sm2();
            // 公钥
            String publickey = sm2.getPublicKeyBase64();
            // 前端公钥
            String publicQkey = HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false));
            // 私钥
            String privatekey = sm2.getPrivateKeyBase64();
            sm2KeyPair = new SM2KeyPair(publickey, publicQkey, privatekey);
        }
        return sm2KeyPair;
    }

    // 公钥加密
    public static String encrypt(String data, String publickey) {
        SM2 sm2 = SmUtil.sm2(null, publickey);
        String encryptStr = sm2.encryptBcd(data, KeyType.PublicKey);
        return encryptStr;
    }

    // 私钥解密 公钥加密密文
    public static String decrypt(String encryptStr) {
        if (!encryptStr.startsWith("04")) {
            encryptStr = "04".concat(encryptStr);
        }
        String privatekey = sm2KeyPair.privateKey;
        SM2 sm2 = SmUtil.sm2(privatekey, null);
        String decryptStr = StrUtil.utf8Str(sm2.decryptFromBcd(encryptStr, KeyType.PrivateKey));
        return decryptStr;
    }

    // 私钥签名
    public static String signByPrivateKey(String data, String privatekey) {
        SM2 sm2 = SmUtil.sm2(privatekey, null);
        String sign = sm2.signHex(HexUtil.encodeHexStr(data));
        return sign;
    }

    // 公钥验签
    public static boolean verifyByPublicKey(String data, String publickey, String signature) {
        SM2 sm2 = SmUtil.sm2(null, publickey);
        boolean verify = sm2.verifyHex(HexUtil.encodeHexStr(data), signature);
        return verify;
    }

    public static class SM2PublicKey {
        String publicKey;

        public String getPublicKey() {
            return publicKey;
        }


        public SM2PublicKey(String publicKey) {
            this.publicKey = publicKey;
        }
    }

}
